package com.fmy.springbootutils.util;


import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import javax.swing.filechooser.FileSystemView;
import java.io.File;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.lang.reflect.Array;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.net.URISyntaxException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.text.DecimalFormat;
import java.text.MessageFormat;
import java.text.NumberFormat;
import java.util.*;
import java.util.regex.Pattern;

/**
 * 高频方法类
 */
public class ToolUtil {

    /**
     * 将一个double转换成十六进制
     *
     * @param temp
     * @return 高字节在前、低字节在后
     */
    public static byte[] getXsdzValue(Double temp) {
        byte[] b = new byte[2];
        int t = ToolUtil.toInt(temp * 10);
        if (temp < 0) {
            t = ToolUtil.toInt(temp * -10);
        }
        if (temp < 0) {
            b[0] = (byte) ((0xff & (t >> 8)) | 128);
        } else {
            b[0] = (byte) ((0xff & (t >> 8)));
        }
        b[1] = (byte) (0xff & t);
        return b;
    }

    /**
     * 16字节进制转10进制字符串
     *
     * @param byteArray
     * @return
     */
    public static String toHexString(byte[] byteArray) {
        String str = null;
        if (byteArray != null && byteArray.length > 0) {
            StringBuffer stringBuffer = new StringBuffer(byteArray.length);
            for (byte byteChar : byteArray) {
                stringBuffer.append(String.format("%02X", byteChar));
            }
            str = stringBuffer.toString();
        }
        return str;
    }


    /**
     * 十六进制字节转10进制字符串
     * (1) 相当于换种写法、可以支持单个字节转换
     *
     * @param bytes
     * @return
     */
    public static String toHexStrings(byte... bytes) {
        return toHexString(bytes);
    }

    /**
     * 十六进制转十进制
     *
     * @param bytes
     * @return
     */
    public static Integer toHexInt(byte... bytes) {
        String str = toHexStrings(bytes);
        return Integer.valueOf(str, 16);
    }


    /**
     * 10进制字符串转16进制字节
     *
     * @param hexString
     * @return
     */
    public static byte[] hexStringToBytes(String hexString) {
        if (hexString == null || hexString.equals("")) {
            return null;
        }
        hexString = hexString.toUpperCase();
        int length = hexString.length() / 2;
        char[] hexChars = hexString.toCharArray();
        byte[] d = new byte[length];
        for (int i = 0; i < length; i++) {
            int pos = i * 2;
            d[i] = (byte) (charToByte(hexChars[pos]) << 4 | charToByte(hexChars[pos + 1]));
        }
        return d;
    }

    private static byte charToByte(char c) {
        return (byte) "0123456789ABCDEF".indexOf(c);
    }

    public static final NumberFormat format = new DecimalFormat("###,##0.00");

    /**
     * 获取随机位数的字符串
     *
     * @author fengshuonan
     * @Date 2017/8/24 14:09
     */
    public static String getRandomString(int length) {
        String base = "abcdefghijklmnopqrstuvwxyz0123456789";
        Random random = new Random();
        StringBuffer sb = new StringBuffer();
        for (int i = 0; i < length; i++) {
            int number = random.nextInt(base.length());
            sb.append(base.charAt(number));
        }
        return sb.toString();
    }

    /**
     * 获取异常的具体信息
     *
     * @author fengshuonan
     * @Date 2017/3/30 9:21
     * @version 2.0
     */
    public static String getExceptionMsg(Exception e) {
        StringWriter sw = new StringWriter();
        try {
            e.printStackTrace(new PrintWriter(sw));
        } finally {
            try {
                sw.close();
            } catch (IOException e1) {
                e1.printStackTrace();
            }
        }
        return sw.getBuffer().toString().replaceAll("\\$", "T");
    }

    /**
     * 比较两个对象是否相等。<br>
     * 相同的条件有两个，满足其一即可：<br>
     * 1. obj1 == null && obj2 == null; 2. obj1.equals(obj2)
     *
     * @param obj1 对象1
     * @param obj2 对象2
     * @return 是否相等
     */
    public static boolean equals(Object obj1, Object obj2) {
        return (obj1 != null) ? (obj1.equals(obj2)) : (obj2 == null);
    }

    /**
     * 计算对象长度，如果是字符串调用其length函数，集合类调用其size函数，数组调用其length属性，其他可遍历对象遍历计算长度
     *
     * @param obj 被计算长度的对象
     * @return 长度
     */
    public static int length(Object obj) {
        if (obj == null) {
            return 0;
        }
        if (obj instanceof CharSequence) {
            return ((CharSequence) obj).length();
        }
        if (obj instanceof Collection) {
            return ((Collection<?>) obj).size();
        }
        if (obj instanceof Map) {
            return ((Map<?, ?>) obj).size();
        }

        int count;
        if (obj instanceof Iterator) {
            Iterator<?> iter = (Iterator<?>) obj;
            count = 0;
            while (iter.hasNext()) {
                count++;
                iter.next();
            }
            return count;
        }
        if (obj instanceof Enumeration) {
            Enumeration<?> enumeration = (Enumeration<?>) obj;
            count = 0;
            while (enumeration.hasMoreElements()) {
                count++;
                enumeration.nextElement();
            }
            return count;
        }
        if (obj.getClass().isArray() == true) {
            return Array.getLength(obj);
        }
        return -1;
    }

    /**
     * 对象中是否包含元素
     *
     * @param obj     对象
     * @param element 元素
     * @return 是否包含
     */
    public static boolean contains(Object obj, Object element) {
        if (obj == null) {
            return false;
        }
        if (obj instanceof String) {
            if (element == null) {
                return false;
            }
            return ((String) obj).contains(element.toString());
        }
        if (obj instanceof Collection) {
            return ((Collection<?>) obj).contains(element);
        }
        if (obj instanceof Map) {
            return ((Map<?, ?>) obj).values().contains(element);
        }

        if (obj instanceof Iterator) {
            Iterator<?> iter = (Iterator<?>) obj;
            while (iter.hasNext()) {
                Object o = iter.next();
                if (equals(o, element)) {
                    return true;
                }
            }
            return false;
        }
        if (obj instanceof Enumeration) {
            Enumeration<?> enumeration = (Enumeration<?>) obj;
            while (enumeration.hasMoreElements()) {
                Object o = enumeration.nextElement();
                if (equals(o, element)) {
                    return true;
                }
            }
            return false;
        }
        if (obj.getClass().isArray() == true) {
            int len = Array.getLength(obj);
            for (int i = 0; i < len; i++) {
                Object o = Array.get(obj, i);
                if (equals(o, element)) {
                    return true;
                }
            }
        }
        return false;
    }

    /**
     * 对象是否不为空(新增)
     *
     * @param o String,List,Map,Object[],int[],long[]
     * @return
     */
    public static boolean isNotEmpty(Object o) {
        return !isEmpty(o);
    }

    /**
     * 对象是否为空
     *
     * @param o String,List,Map,Object[],int[],long[]
     * @return
     */
    @SuppressWarnings("rawtypes")
    public static boolean isEmpty(Object o) {
        if (o == null) {
            return true;
        }
        if (o instanceof String) {
            if (o.toString().trim().equals("")) {
                return true;
            }
        } else if (o instanceof List) {
            if (((List) o).size() == 0) {
                return true;
            }
        } else if (o instanceof Map) {
            if (((Map) o).size() == 0) {
                return true;
            }
        } else if (o instanceof Set) {
            if (((Set) o).size() == 0) {
                return true;
            }
        } else if (o instanceof Object[]) {
            if (((Object[]) o).length == 0) {
                return true;
            }
        } else if (o instanceof int[]) {
            if (((int[]) o).length == 0) {
                return true;
            }
        } else if (o instanceof long[]) {
            if (((long[]) o).length == 0) {
                return true;
            }
        }
        return false;
    }

    /**
     * 对象组中是否存在 Empty Object
     *
     * @param os 对象组
     * @return
     */
    public static boolean isOneEmpty(Object... os) {
        for (Object o : os) {
            if (isEmpty(o)) {
                return true;
            }
        }
        return false;
    }

    /**
     * 对象组中是否全是 Empty Object
     *
     * @param os
     * @return
     */
    public static boolean isAllEmpty(Object... os) {
        for (Object o : os) {
            if (!isEmpty(o)) {
                return false;
            }
        }
        return true;
    }

    /**
     * 是否为整数
     *
     * @param str
     * @return 是否为整数
     */
    public static boolean isInteger(String str) {
        Pattern pattern = Pattern.compile("^[-\\+]?[\\d]*$");
        return pattern.matcher(str).matches();
    }

    /**
     * 是否为数字
     *
     * @param obj
     * @return
     */
    public static boolean isNum(Object obj) {
        try {
            Integer.parseInt(obj.toString());
        } catch (Exception e) {
            return false;
        }
        return true;
    }

    /**
     * 如果为空, 则调用默认值
     *
     * @param str
     * @return
     */
    public static Object getValue(Object str, Object defaultValue) {
        if (isEmpty(str)) {
            return defaultValue;
        }
        return str;
    }

    /**
     * 强转->string,并去掉多余空格
     *
     * @param str
     * @return
     */
    public static String toStr(Object str) {
        return toStr(str, "");
    }

    /**
     * 强转->string,并去掉多余空格
     *
     * @param str
     * @param defaultValue
     * @return
     */
    public static String toStr(Object str, String defaultValue) {
        if (null == str) {
            return defaultValue;
        }
        return str.toString().trim();
    }

    /**
     * map的key转为小写
     *
     * @param map
     * @return
     */
    public static Map<String, Object> caseInsensitiveMap(Map<String, Object> map) {
        Map<String, Object> tempMap = new HashMap<>();
        for (String key : map.keySet()) {
            tempMap.put(key.toLowerCase(), map.get(key));
        }
        return tempMap;
    }

    /**
     * 字符串首字母转小写
     *
     * @param str 传入字符串
     * @return
     */
    public static String strFirstToLower(String str) {
        char[] ch = str.toCharArray();
        ch[0] = Character.toLowerCase(ch[0]);
        return String.valueOf(ch);
    }

    /**
     * 获取map中第一个数据值
     *
     * @param <K> Key的类型
     * @param <V> Value的类型
     * @param map 数据源
     * @return 返回的值
     */
    public static <K, V> V getFirstOrNull(Map<K, V> map) {
        V obj = null;
        for (Map.Entry<K, V> entry : map.entrySet()) {
            obj = entry.getValue();
            if (obj != null) {
                break;
            }
        }
        return obj;
    }

    /**
     * 创建StringBuilder对象
     *
     * @return StringBuilder对象
     */
    public static StringBuilder builder(String... strs) {
        final StringBuilder sb = new StringBuilder();
        for (String str : strs) {
            sb.append(str);
        }
        return sb;
    }

    /**
     * 创建StringBuilder对象
     *
     * @return StringBuilder对象
     */
    public static void builder(StringBuilder sb, String... strs) {
        for (String str : strs) {
            sb.append(str);
        }
    }

    /**
     * 去掉指定后缀
     *
     * @param str    字符串
     * @param suffix 后缀
     * @return 切掉后的字符串，若后缀不是 suffix， 返回原字符串
     */
    public static String removeSuffix(String str, String suffix) {
        if (isEmpty(str) || isEmpty(suffix)) {
            return str;
        }

        if (str.endsWith(suffix)) {
            return str.substring(0, str.length() - suffix.length());
        }
        return str;
    }


    /**
     * 判断是否是windows操作系统
     *
     * @author stylefeng
     * @Date 2017/5/24 22:34
     */
    public static Boolean isWinOs() {
        String os = System.getProperty("os.name");
        if (os.toLowerCase().startsWith("win")) {
            return true;
        } else {
            return false;
        }
    }

    /**
     * 获取临时目录
     *
     * @author stylefeng
     * @Date 2017/5/24 22:35
     */
    public static String getTempPath() {
        return System.getProperty("java.io.tmpdir");
    }

    /**
     * 把一个数转化为int
     *
     * @author fengshuonan
     * @Date 2017/11/15 下午11:10
     */
    public static Integer toInt(Object val) {
        if (val instanceof Double) {
            BigDecimal bigDecimal = new BigDecimal((Double) val);
            return bigDecimal.intValue();
        } else {
            return Integer.valueOf(val.toString());
        }

    }

    /**
     * 把一个数转化为int
     *
     * @param defaultVal 默认值
     * @author fengshuonan
     * @Date 2017/11/15 下午11:10
     */
    public static Integer toInt(Object val, int defaultVal) {
        if (isEmpty(val)) {
            return defaultVal;
        }
        if (val instanceof Double) {
            BigDecimal bigDecimal = new BigDecimal((Double) val);
            return bigDecimal.intValue();
        } else {
            return Integer.valueOf(val.toString());
        }

    }

    public static BigDecimal toBigDecimal(Object value) {
        BigDecimal ret = null;
        if (value != null) {
            if (value instanceof BigDecimal) {
                ret = (BigDecimal) value;
            } else if (value instanceof String) {
                ret = new BigDecimal((String) value);
            } else if (value instanceof BigInteger) {
                ret = new BigDecimal((BigInteger) value);
            } else if (value instanceof Number) {
                ret = new BigDecimal(((Number) value).doubleValue());
            } else {
                throw new ClassCastException("Not possible to coerce [" + value + "] from class " + value.getClass() + " into a BigDecimal.");
            }
        }
        return ret;
    }

    /**
     * 获取项目路径
     */
    public static String getWebRootPath(String filePath) {
        try {
            String path = ToolUtil.class.getClassLoader().getResource("").toURI().getPath();
            path = path.replace("/WEB-INF/classes/", "");
            path = path.replace("/target/classes/", "");
            path = path.replace("file:/", "");
            if (ToolUtil.isEmpty(filePath)) {
                return path;
            } else {
                return path + "/" + filePath;
            }
        } catch (URISyntaxException e) {
            throw new RuntimeException(e);
        }
    }

    public static String getRootPath() {
        return System.getProperty("user.dir");
    }


    /**
     * 生成随机字符
     *
     * @param n 生成几位字符
     */
    public static String str(int n) {
        String CHARS = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
        boolean[] bools = new boolean[CHARS.length()];
        Random random = new Random();
        StringBuilder sb = new StringBuilder();
        int i = random.nextInt(CHARS.length());
        //循环n次，生成n个字符
        for (int j = 0; j < n; j++) {
            //如果这个位置的bools的值为true,说明这个位置的字符已经出现过来，需要重新产生一个随机数
            while (bools[i]) {
                i = random.nextInt(CHARS.length());
            }
            //生成了一个随机数之后就把对应位置的bools的值改为true
            bools[i] = true;
            sb.append(CHARS.charAt(i));
        }
        return sb.toString();
    }

    /**
     * MD5 32位加密算法
     */
    public static String MD5(String text, String salt) {
        try {
            MessageDigest digest = MessageDigest.getInstance("md5");
            byte[] result = digest.digest((text + salt).getBytes());
            StringBuffer buffer = new StringBuffer();
            for (byte b : result) {
                int number = b & 0xff;
                String str = Integer.toHexString(number);
                if (str.length() == 1) {
                    buffer.append("0");
                }
                buffer.append(str);
            }
            // 标准的md5加密后的结果
            return buffer.toString();
        } catch (NoSuchAlgorithmException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * AES加密
     *
     * @param strKey 秘钥
     * @param strIn  加密内容
     * @return
     * @throws Exception
     */
    public static String encrypt(String strKey, String strIn) throws Exception {
        SecretKeySpec skeySpec = getKey(strKey);
        Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
        IvParameterSpec iv = new IvParameterSpec("01Gx03Yx05WW0607".getBytes());
        cipher.init(Cipher.ENCRYPT_MODE, skeySpec, iv);
        byte[] encrypted = cipher.doFinal(strIn.getBytes());

        return Base64.getEncoder().encodeToString(encrypted);
    }

    /**
     * AES解密
     *
     * @param strKey 秘钥
     * @param strIn  解密内容
     * @return
     * @throws Exception
     */
    public static String decrypt(String strKey, String strIn) throws Exception {
        SecretKeySpec skeySpec = getKey(strKey);
        Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
        IvParameterSpec iv = new IvParameterSpec("01Gx03Yx05WW0607".getBytes());
        cipher.init(Cipher.DECRYPT_MODE, skeySpec, iv);
        byte[] encrypted1 = Base64.getDecoder().decode(strIn);

        byte[] original = cipher.doFinal(encrypted1);
        String originalString = new String(original);
        return originalString;
    }

    private static SecretKeySpec getKey(String strKey) throws Exception {
        byte[] arrBTmp = strKey.getBytes();
        byte[] arrB = new byte[16]; // 创建一个空的16位字节数组（默认值为0）
        for (int i = 0; i < arrBTmp.length && i < arrB.length; i++) {
            arrB[i] = arrBTmp[i];
        }
        SecretKeySpec skeySpec = new SecretKeySpec(arrB, "AES");

        return skeySpec;
    }


    /**
     * 判断当前目录是否存在，如果不存在就创建，存在则什么都不做
     *
     * @param file
     * @return
     */
    public static void fileExists(File file) {
        if (!file.exists()) {
            file.mkdirs();
        }
    }

    /**
     * 删除单个文件
     *
     * @param fileName 要删除的文件的文件路径包含文件名
     * @return 单个文件删除成功返回true，否则返回false
     */
    public static boolean deleteFile(String fileName) {
        File file = new File(fileName);
        // 如果文件路径所对应的文件存在，并且是一个文件，则直接删除
        if (file.exists() && file.isFile()) {
            if (file.delete()) {
                return true;
            } else {
                return false;
            }
        } else {
            return false;
        }
    }

    /**
     * java获取桌面路径
     */
    public static String getHomeDirectory() {
        FileSystemView fsv = FileSystemView.getFileSystemView();
        File com = fsv.getHomeDirectory();    //这便是读取桌面路径的方法了
        return com.getPath();
    }

    /**
     * 集合实体类转Map
     *
     * @param list
     * @param bolFalse
     * @return
     */
    public static List<Map<String, Object>> entityToMaps(List list, boolean bolFalse) {
        List<Map<String, Object>> listMap = new ArrayList<>();
        for (Object o : list) {
            listMap.add(entityToMap(o, bolFalse));
        }
        return listMap;
    }

    /**
     * 实体类转Map 如果该属性为NULL则不转换
     * is开头的boolean基于转换时调用的是 getIs字段
     * 请确保有该方法、请不要传入集合、其中实体类的属性
     * 中如果存在list或者map类型的属性则该属性不映射
     *
     * @param o        传入实体类
     * @param bolFalse 是否映射 布尔类型为false字段、如果
     *                 该参数为TRUE 则映射、否则放弃映射
     *                 例如该参数为true、实体类中有一布尔类型为fasle那么
     *                 将会把该布尔类型字段映射进入Map反义不映射、但是如果
     *                 该布尔类型为TRUE 那么始终会映射该属性
     * @return
     */
    public static Map<String, Object> entityToMap(Object o, boolean bolFalse) {
        Map<String, Object> map = new HashMap<>();
        Method[] methods = o.getClass().getMethods();
        //获取所有get方法
        for (Method method : methods) {
            String methodName = method.getName();//获取该方法名称
            if ("getclasee".equalsIgnoreCase(methodName)) {//getClass方法不进行转换
                continue;
            }
            if (methodName.substring(0, 3).equals("get")) {//判断其方法是否是GET方法
                String propertyName = strFirstToLower(methodName.substring(3, methodName.length()));//获取其字段名并首字母转小写
                //获取其值
                try {
                    Object value = method.invoke(o);
                    if (value instanceof List || value instanceof Map) {//list或map不转换
                        continue;
                    }
                    if (value instanceof Boolean) {
                        if (!(boolean) value && bolFalse) {
                            map.put(propertyName, value);
                        } else {
                            map.put(propertyName, value);
                        }
                        continue;
                    }
                    if (value != null) {
                        map.put(propertyName, value);
                        continue;
                    }
                } catch (IllegalAccessException e) {
                    throw new RuntimeException("实体类转换Map异常");
                } catch (InvocationTargetException e) {
                    throw new RuntimeException("实体类转换Map异常");
                }
            }
        }
        return map;
    }

    /**
     * 判断值是否为空 如何为空赋值Param2 否则是原值param1
     *
     * @param param1 判断值
     * @param Param2 默认值
     * @return
     */
    public static Object isNUllChangeParam(Object param1, Object Param2) {
        if (ToolUtil.isEmpty(param1)) {
            return Param2;
        } else {
            return param1;
        }
    }

    /**
     * 传入 分页页数、如果为0或为NULL或为负数、自动为1
     *
     * @param page
     * @return
     */
    public static Integer getPage(Integer page) {
        if (page == null || page <= 0) {
            return 1;
        }
        return page;
    }

    /**
     * 获取计算方式为 (page-1) * limit
     *
     * @param page  当前页数
     * @param limie 分页数
     * @return (page - 1) * limit
     */
    public static Integer getPage(Integer page, Integer limie) {
        if (page == null || page <= 0) {
            page = 1;
        }
        return (page - 1) * limie;
    }

    /**
     * 直接保留两位小数、不进行任何四舍五入
     *
     * @param bigDecimal
     * @return
     */
    public static BigDecimal KeepPosition(BigDecimal bigDecimal) {
        return bigDecimal.setScale(2, BigDecimal.ROUND_DOWN);
    }

    /**
     * 日期字符串转换为 年月日时分秒
     *
     * @param str
     * @param length 截取类型   4  7  10 13 16 19
     * @return
     */
    public static String substr(String str, Integer length) {
        if (ToolUtil.isEmpty(length)) {
            length = 19;
        }
        String value = "";
        value = value + str.substring(0, 4) + "年";
        if (length == 4) {
            return value;
        }
        value = value + str.substring(5, 7) + "月";
        if (length == 7) {
            return value;
        }
        value = value + str.substring(8, 10) + "日";
        if (length == 10) {
            return value;
        }
        value = value + str.substring(11, 13) + "时";
        if (length == 13) {
            return value;
        }
        value = value + str.substring(14, 16) + "分";
        if (length == 16) {
            return value;
        }
        value = value + str.substring(17, 19) + "秒";
        return value;
    }

    /**
     * mysql日期函数拼接方法、默认为日
     * 日格式：yyyy-MM-dd
     * 周格式：yyyyZZ  zz代表几周、例如：201901  为2019年第一周
     * 月格式：yyyy-MM
     * 季度格式：1~4 数字代表 统计季度时最好多加一个年类型判断
     * 年格式：yyyy
     *
     * @param coloum 列名
     * @param type   类型 4：年、5：周 6、季度、7：月、10：日统 默认日统
     * @return 格式化后的列名
     */
    public static String mysqlDateFormat(String coloum, int type) {
        String typeFormat = "'%Y-%m-%d'";
        switch (type) {
            case 4:
                typeFormat = "'%Y'";
                break;
            case 5:
                return MessageFormat.format("YEARWEEK({0},4)", coloum);
            case 6:
                return MessageFormat.format("quarter({0})", coloum);
            case 7:
                typeFormat = "'%Y-%m'";
                break;
            case 10:
                typeFormat = "'%Y-%m-%d'";
                break;
        }
        return MessageFormat.format("date_format({0},{1})", coloum, typeFormat);
    }

    /**
     * 转换时间
     *
     * @param time       时间
     * @param type       类型 4：年、5：周 7：月、10：日
     * @param connectStr 时间连接符、如 2019-01-02 连接符为 `-`
     * @return
     */
    public static String dataFormat(String time, int type, String connectStr) {
        switch (type) {
            case 4:
                return time + "年";
            case 5:
                //得到前4位
                String year = time.substring(0, 4);
                return year + "年" + time.substring(4, 6) + "周";
            case 7:
                return time.replaceFirst(connectStr, "年") + "月";
            case 10:
                return time.replaceFirst(connectStr, "年").replaceFirst(connectStr, "月") + "日";
        }
        return time;
    }

    /**
     * 数字金额大写转换，思想先写个完整的然后将如零拾替换成零 要用到正则表达式
     */
    public static String digitUppercase(double n) {
        String fraction[] = {"角", "分"};
        String digit[] = {"零", "壹", "贰", "叁", "肆", "伍", "陆", "柒", "捌", "玖"};
        String unit[][] = {{"元", "万", "亿"}, {"", "拾", "佰", "仟"}};

        String head = n < 0 ? "负" : "";
        n = Math.abs(n);

        String s = "";
        for (int i = 0; i < fraction.length; i++) {
            s += (digit[(int) (Math.floor(n * 10 * Math.pow(10, i)) % 10)] + fraction[i]).replaceAll("(零.)+", "");
        }
        if (s.length() < 1) {
            s = "整";
        }
        int integerPart = (int) Math.floor(n);

        for (int i = 0; i < unit[0].length && integerPart > 0; i++) {
            String p = "";
            for (int j = 0; j < unit[1].length && n > 0; j++) {
                p = digit[integerPart % 10] + unit[1][j] + p;
                integerPart = integerPart / 10;
            }
            s = p.replaceAll("(零.)*零$", "").replaceAll("^$", "零") + unit[0][i] + s;
        }
        return head + s.replaceAll("(零.)*零元", "元").replaceFirst("(零.)+", "").replaceAll("(零.)+", "零").replaceAll("^整$", "零元整");
    }

    /**
     * 正则表达式忽略大小写判断
     *
     * @param pattern 表达式
     * @param index   效验的字符
     * @return 是否符合要求
     */
    public static boolean patternCase(String pattern, String index) {
        return Pattern.compile(pattern, Pattern.CASE_INSENSITIVE).matcher(index).matches();
    }

    public static int page(Integer page) {
        return page == null || page <= 0 ? 1 : page;
    }

    public static int limit(Integer limit) {
        return limit == null || limit <= 0 ? 10 : limit;
    }

    /**
     * 字符串比较
     *
     * @param str       需要比对的字符串
     * @param connector true为and false为or
     * @param strs      对比的字符串
     * @return
     */
    public static boolean strEquals(String str, boolean connector, String... strs) {
        if (ToolUtil.isEmpty(strs) || ToolUtil.isEmpty(str)) return false;
        for (String item : strs) {
            if (item.equals(str)) {
                if (!connector) {
                    return true;
                }
            } else {
                if (connector) {
                    return false;
                }
            }
        }
        return connector ? true : false;
    }

    /**
     * 字符串 前补位
     *
     * @param str      字符串
     * @param position 补位
     * @param num      不足多少补位
     * @return
     */
    public static String strFirstPosition(String str, String position, int num) {
        if (str != null) {
            return str.length() < num ? position + str : str;
        }
        return position;
    }
}
